package decoder

import (
	"bytes"
	"fmt"
	"pmservice/ecgpacket"
	hl7d "pmservice/hl7decoder"
	"pmservice/logger"
	"strconv"
	"strings"
)

// 浮点数通道需要乘以一个系数转为整数, 使用方需要相应的除以此系数
var EcgChanCoff = map[ecgpacket.EcgChan]float64{
	ecgpacket.EcgChan_CHAN_TEMP_1:    10.0,
	ecgpacket.EcgChan_CHAN_TEMP_2:    10.0,
	ecgpacket.EcgChan_CHAN_TEMP_DIFF: 10.0,
}

// HL7 Internal message data per line
// only save useful data
// MSH|^~\&|XH80X^XH80YYMMDDXXXX^EUI-64|XH80X^0101010001040900^EUI-64|||20230917033544000+0000||ORU^R01^ORU_R01|41|P|2.4|2764||AL|NE||UNICODE UTF-8
type hl7_MSH struct {
	MSH31_NamespaceID      string
	MSH32_UniversalID      string
	MSH33_UniversalIDType  string // "EUI-64"
	MSH41_NamespaceID      string
	MSH42_UniversalID      string
	MSH43_UniversalIDType  string // "EUI-64"
	MSH7_MessageDateTime   string // YYYYMMDDHHMMSSmmm+/-ZZZZ
	MSH91                  string // "ORU"
	MSH92                  string // "R01"
	MSH93                  string // "ORU_R01"
	MSH10_MessageControlID string
	MSH11_1                string // "P"
	MSH12_VersionID        string // "2.4"
	MSH13_SequenceNumber   string
	MSH15                  string // "AL"
	MSH16                  string // "NE"
	MSH18                  string // "UNICODE UTF-8"
}

func (m *hl7_MSH) parse(seg hl7d.Segment) bool {

	if len(seg.Fields) < 19 {
		// return errors.New("segment fileds is not enough to parse msh")
		return false
	}

	if string(seg.Fields[0].Value) != "MSH" {
		return false
	}

	if len(seg.Fields[3].Components) < 3 {
		// return errors.New("fileds is not enough to parse msh")
		return false
	}

	if len(seg.Fields[4].Components) < 3 {
		// return errors.New("fileds is not enough to parse msh")
		return false
	}

	if len(seg.Fields[9].Components) < 3 {
		// return errors.New("fileds is not enough to parse msh")
		return false
	}

	m.MSH31_NamespaceID = string(seg.Fields[3].Components[0].Value)
	m.MSH32_UniversalID = string(seg.Fields[3].Components[1].Value)
	m.MSH33_UniversalIDType = string(seg.Fields[3].Components[2].Value)
	m.MSH41_NamespaceID = string(seg.Fields[4].Components[0].Value)
	m.MSH42_UniversalID = string(seg.Fields[4].Components[1].Value)
	m.MSH43_UniversalIDType = string(seg.Fields[4].Components[2].Value)
	m.MSH7_MessageDateTime = string(seg.Fields[7].Value)
	m.MSH91 = string(seg.Fields[9].Components[0].Value)
	m.MSH92 = string(seg.Fields[9].Components[1].Value)
	m.MSH93 = string(seg.Fields[9].Components[2].Value)
	m.MSH11_1 = string(seg.Fields[11].Components[0].Value)
	m.MSH12_VersionID = string(seg.Fields[12].Value)
	m.MSH13_SequenceNumber = string(seg.Fields[13].Value)
	m.MSH15 = string(seg.Fields[15].Value)
	m.MSH16 = string(seg.Fields[16].Value)
	m.MSH18 = string(seg.Fields[18].Value)

	return true
}

// PID|||^^^^PI||^^^^^^L||20230917000000000+0000|M||||||||||||||||||||||||||||||||ADU
type hl7_PID struct {
	PID31_IDNumber         string
	PID34_Facility         string
	PID35_IdentifyTypeCode string // "PI"
	PID51_FamilyName       string
	PID52_GivenName        string
	PID53_SndGivenName     string
	PID57_NameTypeCode     string // "L"
	PID7_DateTimeOfBirth   string // YYYYMMDDHHMMSSmmm+/-ZZZZ
	PID8_AdminSex          string // <blank>/M/F/U
	PID10_Race             string
	PID40_AgeGroup         string // <blank>/Adu/Ped/Neo/Unknown
}

func (m *hl7_PID) parse(seg hl7d.Segment) bool {
	if len(seg.Fields) < 41 {
		return false
	}

	if string(seg.Fields[0].Value) != "PID" {
		return false
	}

	if len(seg.Fields[3].Components) < 5 {
		return false
	}

	if len(seg.Fields[5].Components) < 7 {
		return false
	}

	m.PID31_IDNumber = string(seg.Fields[3].Components[0].Value)
	m.PID34_Facility = string(seg.Fields[3].Components[3].Value)
	m.PID35_IdentifyTypeCode = string(seg.Fields[3].Components[4].Value)
	m.PID51_FamilyName = string(seg.Fields[5].Components[0].Value)
	m.PID52_GivenName = string(seg.Fields[5].Components[1].Value)
	m.PID53_SndGivenName = string(seg.Fields[5].Components[2].Value)
	m.PID57_NameTypeCode = string(seg.Fields[5].Components[6].Value)
	m.PID7_DateTimeOfBirth = string(seg.Fields[7].Value)
	m.PID8_AdminSex = string(seg.Fields[8].Value)
	m.PID10_Race = string(seg.Fields[10].Value)
	m.PID40_AgeGroup = string(seg.Fields[40].Value)

	return true
}

// PV1||I|^^1^||||||||||||||||||||||||||||||||||||||||20230917000000000+0000|||||||||||
type hl7_PV1 struct {
	// PV12_PatientClass       string // "I"
	// PV131_PointOfCare       string
	// PV132_Room              string
	// PV133_Bed               string
	// PV134_Facility          string
	// PV171_IDNumber          string
	// PV172_FamilyName        string
	// PV173_GivenName         string
	// PV174_SndGivenName      string
	// PV144_AdmitDateTime     string // YYYYMMDDHHMMSSmmm+/-ZZZZ
	// PV144_DischargeDateTime string // YYYYMMDDHHMMSSmmm+/-ZZZZ
	// PV155_Indication        string
}

func (m *hl7_PV1) parse(seg hl7d.Segment) bool {
	if len(seg.Fields) < 55 {
		return false
	}

	if string(seg.Fields[0].Value) != "PV1" {
		return false
	}

	// if len(seg.Fields[3].Components) < 4 {
	// 	return false
	// }

	// if len(seg.Fields[7].Components) < 4 {
	// 	return false
	// }

	// m.PV12_PatientClass = string(seg.Fields[2].Value)
	// m.PV131_PointOfCare = string(seg.Fields[3].Components[0].Value)
	// m.PV132_Room = string(seg.Fields[3].Components[1].Value)
	// m.PV133_Bed = string(seg.Fields[3].Components[2].Value)
	// m.PV134_Facility = string(seg.Fields[3].Components[3].Value)
	// m.PV171_IDNumber = string(seg.Fields[7].Components[0].Value)
	// m.PV172_FamilyName = string(seg.Fields[7].Components[1].Value)
	// m.PV173_GivenName = string(seg.Fields[7].Components[2].Value)
	// m.PV174_SndGivenName = string(seg.Fields[7].Components[3].Value)
	// m.PV144_AdmitDateTime = string(seg.Fields[44].Value)
	// m.PV155_Indication = string(seg.Fields[55].Value)

	return true
}

// Observation Block OBR Segment
// OBR|1|41^XH80X^XH80YYMMDDXXXX^EUI-64|41^XH80X^XH80YYMMDDXXXX^EUI-64|182777000^monitoring of patient^SCT|||20230917033455000+0000
type hl7_OBR_ObservationBlock struct {
	OBR1_ID                    string
	OBR21_EntityIdentifier     string // Same as MSH10
	OBR22_NamespaceID          string // Same as MSH31
	OBR23_UniversalID          string // Same as MSH32
	OBR24_UniversalIDType      string // "EUI-64"
	OBR31_EntityIdentifier     string // Same as OBR21
	OBR32_NamespaceID          string // Same as OBR22
	OBR33_UniversalID          string // Same as OBR23
	OBR34_UniversalIDType      string // "EUI-64"
	OBR41_Identifier           string // "182777000"
	OBR42_Text                 string // "monitoring of patient"
	OBR43_NamingOfCodingSystem string // "SCT"
	OBR7_ObservationDateTime   string // YYYYMMDDHHMMSSmmm+/-ZZZZ
}

func (m *hl7_OBR_ObservationBlock) parse(seg hl7d.Segment) bool {
	if len(seg.Fields) < 8 {
		return false
	}

	if string(seg.Fields[0].Value) != "OBR" {
		return false
	}

	if len(seg.Fields[2].Components) < 4 {
		return false
	}

	if len(seg.Fields[3].Components) < 4 {
		return false
	}

	if len(seg.Fields[4].Components) < 3 {
		return false
	}

	m.OBR1_ID = string(seg.Fields[1].Value)
	m.OBR21_EntityIdentifier = string(seg.Fields[2].Components[0].Value)
	m.OBR22_NamespaceID = string(seg.Fields[2].Components[1].Value)
	m.OBR23_UniversalID = string(seg.Fields[2].Components[2].Value)
	m.OBR24_UniversalIDType = string(seg.Fields[2].Components[3].Value)
	m.OBR31_EntityIdentifier = string(seg.Fields[3].Components[0].Value)
	m.OBR32_NamespaceID = string(seg.Fields[3].Components[1].Value)
	m.OBR33_UniversalID = string(seg.Fields[3].Components[2].Value)
	m.OBR34_UniversalIDType = string(seg.Fields[3].Components[3].Value)
	m.OBR41_Identifier = string(seg.Fields[4].Components[0].Value)
	m.OBR42_Text = string(seg.Fields[4].Components[1].Value)
	m.OBR43_NamingOfCodingSystem = string(seg.Fields[4].Components[2].Value)
	m.OBR7_ObservationDateTime = string(seg.Fields[7].Value)

	return m.OBR42_Text == "monitoring of patient" // service identifier check
}

// OBX|1|NM|188740^MDC_LEN_BODY_ACTUAL^MDC|1.10.1.188740|100.0|263441^MDC_DIM_CENTI_M^MDC||||||||20230917033455000+0000|||^|XH80YYMMDDXXXX^^XH80YYMMDDXXXX^EUI-64
type hl7_OBX_ObservationBlock struct {
	OBX1_ID                      string
	OBX2_ValueType               string // SN/NM/CWE/ST
	OBX3_OversationIdentifier    string
	OBX31_Identifier             string
	OBX32_Text                   string
	OBX33_NameOfCodingSystem     string // “MDC”/"WL"
	OBX4_ObservationSubID        string //
	OBX5_ObservationValue        string
	OBX6_Units                   string
	OBX8_AbnormalFlags           string // INV/DEMO
	OBX11_ObersationResultStatus string // R/F/X
	OBX14_ObersationDateTime     string // YYYYMMDDHHMMSSmmm+/-ZZZZ
	// OBX17_2_OvercationMethod     string
	// OBX18_1 string // MSH32
	// OBX18_3 string // MSH32
	// OBX18_4 string // "EUI-64"
}

func (m *hl7_OBX_ObservationBlock) parse(seg hl7d.Segment) bool {
	if len(seg.Fields) < 15 {
		return false
	}

	if string(seg.Fields[0].Value) != "OBX" {
		return false
	}

	if len(seg.Fields[3].Components) < 3 {
		return false
	}

	m.OBX1_ID = string(seg.Fields[1].Value)
	m.OBX2_ValueType = string(seg.Fields[2].Value)
	m.OBX3_OversationIdentifier = string(seg.Fields[3].Value)
	m.OBX31_Identifier = string(seg.Fields[3].Components[0].Value)
	m.OBX32_Text = string(seg.Fields[3].Components[1].Value)
	m.OBX33_NameOfCodingSystem = string(seg.Fields[3].Components[2].Value)
	m.OBX4_ObservationSubID = string(seg.Fields[4].Value)
	m.OBX5_ObservationValue = string(seg.Fields[5].Value)
	m.OBX6_Units = string(seg.Fields[6].Value)
	m.OBX8_AbnormalFlags = string(seg.Fields[8].Value)
	m.OBX11_ObersationResultStatus = string(seg.Fields[11].Value)
	m.OBX14_ObersationDateTime = string(seg.Fields[14].Value)

	return true
}

// OBR|1||42^XH80X^XH80YYMMDDXXXX^EUI-64|CONTINUOUS WAVEFORM|||20230917033454000+0000|20230917033455000+0000
type hl7_OBR_WaveformBlock struct {
	OBR1_ID                         string
	OBR31_EntityIdentifier          string // Same as MSH10
	OBR32_NamespaceID               string // Same as MSH31
	OBR33_UniversalID               string // Same as MSH32
	OBR34_UniversalIDType           string // "EUI-64"
	OBR4_UniversalServiceIdentifier string // "CONTINUOUS WAVEFORM"
	OBR7_StartTime                  string // YYYYMMDDHHMMSSmmm+/-ZZZZ
	OBR8_EndTime                    string // YYYYMMDDHHMMSSmmm+/-ZZZZ
}

func (m *hl7_OBR_WaveformBlock) parse(seg hl7d.Segment) bool {
	if len(seg.Fields) < 9 {
		return false
	}

	if string(seg.Fields[0].Value) != "OBR" {
		return false
	}

	if len(seg.Fields[3].Components) < 4 {
		return false
	}

	m.OBR1_ID = string(seg.Fields[1].Value)
	m.OBR31_EntityIdentifier = string(seg.Fields[3].Components[0].Value)
	m.OBR32_NamespaceID = string(seg.Fields[3].Components[1].Value)
	m.OBR33_UniversalID = string(seg.Fields[3].Components[2].Value)
	m.OBR34_UniversalIDType = string(seg.Fields[3].Components[3].Value)
	m.OBR4_UniversalServiceIdentifier = string(seg.Fields[4].Value)
	m.OBR7_StartTime = string(seg.Fields[7].Value)
	m.OBR8_EndTime = string(seg.Fields[8].Value)

	return m.OBR4_UniversalServiceIdentifier == "CONTINUOUS WAVEFORM" // service identifier check
}

type hl7_OBX_WaveformBlock struct {
	OBX1_ID                   string
	OBX2_ValueType            string
	OBX3_OversationIdentifier string
	OBX4_ObservationSubID     string
	OBX5_ObservationValue     string
	OBX6_Units                string
	OBX14_ObservationDateTime string // YYYYMMDDHHMMSSmmm+/-ZZZZ
}

func (m *hl7_OBX_WaveformBlock) parse(seg hl7d.Segment) bool {
	if len(seg.Fields) < 6 {
		return false
	}

	if string(seg.Fields[0].Value) != "OBX" {
		return false
	}

	m.OBX1_ID = string(seg.Fields[1].Value)
	m.OBX2_ValueType = string(seg.Fields[2].Value)
	m.OBX3_OversationIdentifier = string(seg.Fields[3].Value)
	m.OBX4_ObservationSubID = string(seg.Fields[4].Value)
	m.OBX5_ObservationValue = string(seg.Fields[5].Value)

	if len(seg.Fields) >= 7 {
		m.OBX6_Units = string(seg.Fields[6].Value)
	}

	if len(seg.Fields) >= 15 {
		m.OBX14_ObservationDateTime = string(seg.Fields[14].Value)
	}

	return true
}

// OBR|1||43^XH80X^XH80YYMMDDXXXX^EUI-64|196616^MDC_EVT_ALARM^MDC|||20230917033456100+0000||||||||||||||||||||||^43
type hl7_OBR_Alert struct {
	OBR1_ID                         string
	OBR31_EntityIdentifier          string // Same as MSH10
	OBR32_NamespaceID               string // Same as MSH31
	OBR33_UniversalID               string // Same as MSH32
	OBR34_UniversalIDType           string // Same as MSH33
	OBR4_UniversalServiceIdentifier string // "196616^MDC_EVT_ALARM^MDC"
	OBR7_ObservationDateTime        string // YYYYMMDDHHMMSSmmm+/-ZZZZ
	OBR29_2                         string
	// OBR29_2_1_EntityIdentifier      string
	// OBR29_2_2_NamespaceID           string
	// OBR29_2_3_UniversalID           string
	// OBR29_2_4_UniversalIDType       string
}

func (m *hl7_OBR_Alert) parse(seg hl7d.Segment) bool {

	if len(seg.Fields) < 30 {
		return false
	}

	if string(seg.Fields[0].Value) != "OBR" {
		return false
	}

	if len(seg.Fields[3].Components) < 4 {
		return false
	}

	if len(seg.Fields[29].Components) < 2 {
		return false
	}

	// if len(seg.Fields[29].Components[1].SubComponents) < 4 {
	// 	return false
	// }

	m.OBR1_ID = string(seg.Fields[1].Value)
	m.OBR31_EntityIdentifier = string(seg.Fields[3].Components[0].Value)
	m.OBR32_NamespaceID = string(seg.Fields[3].Components[1].Value)
	m.OBR33_UniversalID = string(seg.Fields[3].Components[2].Value)
	m.OBR34_UniversalIDType = string(seg.Fields[3].Components[3].Value)
	m.OBR4_UniversalServiceIdentifier = string(seg.Fields[4].Value)
	m.OBR7_ObservationDateTime = string(seg.Fields[7].Value)
	m.OBR29_2 = string(seg.Fields[29].Components[1].Value)
	// m.OBR29_2_1_EntityIdentifier = string(seg.Fields[29].Components[1].SubComponents[0].Value)
	// m.OBR29_2_2_NamespaceID = string(seg.Fields[29].Components[1].SubComponents[1].Value)
	// m.OBR29_2_3_UniversalID = string(seg.Fields[29].Components[1].SubComponents[2].Value)
	// m.OBR29_2_4_UniversalIDType = string(seg.Fields[29].Components[1].SubComponents[3].Value)

	return m.OBR4_UniversalServiceIdentifier == "196616^MDC_EVT_ALARM^MDC" // service identifier check
}

type hl7_OBX_Alert struct {
	OBX1_ID                       string
	OBX2_ValueType                string // ST
	OBX3_OversationIdentifier     string // "68486^MDC_ATTR_ALERT_THRESHOLD^MDC"
	OBX4_ObservationSubID         string // appended with ".8"
	OBX5_ObservationValue         string // CL999L999H999CH999
	OBX11_ObservationResultStatus string // "F"
	OBX14_ObservationDateTime     string
}

func (m *hl7_OBX_Alert) parse(seg hl7d.Segment) bool {
	if len(seg.Fields) < 12 {
		return false
	}

	if string(seg.Fields[0].Value) != "OBX" {
		return false
	}

	m.OBX1_ID = string(seg.Fields[1].Value)
	m.OBX2_ValueType = string(seg.Fields[2].Value)
	m.OBX3_OversationIdentifier = string(seg.Fields[3].Value)
	m.OBX4_ObservationSubID = string(seg.Fields[4].Value)
	m.OBX5_ObservationValue = string(seg.Fields[5].Value)
	m.OBX11_ObservationResultStatus = string(seg.Fields[11].Value)

	if len(seg.Fields) >= 15 {
		m.OBX14_ObservationDateTime = string(seg.Fields[14].Value)
	}

	return true
}

type hl7_ObservationBlock struct {
	obr hl7_OBR_ObservationBlock
	obx []hl7_OBX_ObservationBlock
}

func PackInt32ChanMulVal(ch ecgpacket.EcgChan, vs []float64) *ecgpacket.ChanPacket {
	vi := make([]string, 0)
	for _, v := range vs {
		vi = append(vi, strconv.FormatInt(int64(v), 10))
	}
	return &ecgpacket.ChanPacket{
		Chan:  ch,
		Value: strings.Join(vi, ","),
	}
}

func PaclInt32MulChan(ts int64, pid int64, code int32, cs []*ecgpacket.ChanPacket) *ecgpacket.Packet {
	return &ecgpacket.Packet{
		Timestamp: ts,
		Pid:       pid,
		Ecg: &ecgpacket.Ecg{
			Code: code,
		},
		Patient:   &ecgpacket.Patient{},
		Rawpacket: "",
		Data:      cs,
		Alert:     []*ecgpacket.Alert{},
	}
}

// OBX5_ObservationValue separated by ^
// 53^53^52^52^51^51^51^51^50^50^50^50^49^49^48^48^48^48^47^47
func HL7ValueToSlice(vs string, coff float64) []float64 {
	ret := make([]float64, 0)
	if len(vs) == 0 {
		return ret
	}

	ss := strings.Split(vs, "^")
	for _, s := range ss {
		i, e := strconv.ParseFloat(s, 64)
		if e != nil {
			fmt.Println("ParseFloat err:", s, e)
			return ret
		}
		ret = append(ret, i*coff)
	}

	return ret
}

func (m *hl7_ObservationBlock) PackOBX(obx hl7_OBX_ObservationBlock, ct ecgpacket.EcgChan) *ecgpacket.ChanPacket {
	coff, ok := EcgChanCoff[ct]
	if !ok {
		coff = 1
	}

	vs := HL7ValueToSlice(obx.OBX5_ObservationValue, coff)
	if vs == nil {
		logger.Info("Pack Obr OBX value error:", obx.OBX5_ObservationValue)
		return nil
	}

	return PackInt32ChanMulVal(ct, vs)
}

func (m *hl7_ObservationBlock) Convert() *ecgpacket.Packet {
	// fmt.Println("hl7_ObservationBlock Packet")
	pkt := ecgpacket.Packet{
		Data: make([]*ecgpacket.ChanPacket, 0),
	}
	for _, obx := range m.obx {
		switch obx.OBX3_OversationIdentifier {
		case "188740^MDC_LEN_BODY_ACTUAL^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_LEN_BODY_ACTUAL_HEIGHT))
		case "188736^MDC_MASS_BODY_ACTUAL^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_MASS_BODY_ACTUAL_WEIGHT))
		case "150301^MDC_PRESS_CUFF_SYS^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_PRESS_CUFF_SYS))
		case "150303^MDC_PRESS_CUFF_MEAN^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_PRESS_CUFF_MEAN))
		case "150302^MDC_PRESS_CUFF_DIA^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_PRESS_CUFF_DIA))
		case "149546^MDC_PULS_RATE_NON_INV^MDC":
		case "150300^MDC_PRESS_CUFF^MDC":
		case "150456^MDC_PULS_OXIM_SAT_O2^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_PULS_OXIM_SAT_O2))
		case "149530^MDC_PULS_OXIM_PULS_RATE^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_PULS_OXIM_PULSE_RATE))
		case "150488^MDC_BLD_PERF_INDEX^MDC":
		case "151578^MDC_TTHOR_RESP_RATE^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_TTHOR_RESP_RATE))
		case "150344^MDC_TEMP^MDC":
			if obx.OBX4_ObservationSubID == "1.13.1.150344" {
				pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_TEMP_1))
			} else if obx.OBX4_ObservationSubID == "1.13.2.150344" {
				pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_TEMP_2))
			}
		case "188440^MDC_TEMP_DIFF^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_TEMP_DIFF))
		case "147842^MDC_ECG_HEART_RATE^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_HEART_RATE))
		case "148066^MDC_ECG_V_P_C_RATE^MDC":
		case "131841^MDC_ECG_AMPL_ST_I^MDC":
		case "131842^MDC_ECG_AMPL_ST_II^MDC":
		case "131901^MDC_ECG_AMPL_ST_III^MDC":
		case "131902^MDC_ECG_AMPL_ST_AVR^MDC":
		case "131903^MDC_ECG_AMPL_ST_AVL^MDC":
		case "131904^MDC_ECG_AMPL_ST_AVF^MDC":
		case "131843^MDC_ECG_AMPL_ST_V1^MDC":
		case "131844^MDC_ECG_AMPL_ST_V2^MDC":
		case "131845^MDC_ECG_AMPL_ST_V3^MDC":
		case "131846^MDC_ECG_AMPL_ST_V4^MDC":
		case "131847^MDC_ECG_AMPL_ST_V5^MDC":
		case "131848^MDC_ECG_AMPL_ST_V6^MDC":
		}
	}

	return &pkt

}

func (m *hl7_ObservationBlock) parse(segs []hl7d.Segment) bool {
	if len(segs) < 2 {
		return false
	}

	if !m.obr.parse(segs[0]) {
		return false
	}

	m.obx = make([]hl7_OBX_ObservationBlock, 0)
	for _, seg := range segs[1:] {
		obx := hl7_OBX_ObservationBlock{}
		if obx.parse(seg) {
			m.obx = append(m.obx, obx)
		}
	}

	return true
}

type hl7_WaveBlock struct {
	obr hl7_OBR_WaveformBlock
	obx []hl7_OBX_WaveformBlock
}

func (m *hl7_WaveBlock) PackOBX(obx hl7_OBX_WaveformBlock, ct ecgpacket.EcgChan) *ecgpacket.ChanPacket {
	coff, ok := EcgChanCoff[ct]
	if !ok {
		coff = 1
	}

	vs := HL7ValueToSlice(obx.OBX5_ObservationValue, coff)
	if vs == nil {
		logger.Info("Pack Wave OBX value error:", obx.OBX5_ObservationValue)
		return nil
	}

	c := PackInt32ChanMulVal(ct, vs)
	return c
}

func (m *hl7_WaveBlock) Convert() *ecgpacket.Packet {
	pkt := ecgpacket.Packet{
		Data: make([]*ecgpacket.ChanPacket, 0),
	}

	for _, obx := range m.obx {
		switch obx.OBX3_OversationIdentifier {
		case "131329^MDC_ECG_ELEC_POTL_I^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_I))
		case "131330^MDC_ECG_ELEC_POTL_II^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_II))
		case "131331^MDC_ECG_ELEC_POTL_V1^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_V1))
		case "131332^MDC_ECG_ELEC_POTL_V2^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_V2))
		case "131333^MDC_ECG_ELEC_POTL_V3^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_V3))
		case "131334^MDC_ECG_ELEC_POTL_V4^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_V4))
		case "131335^MDC_ECG_ELEC_POTL_V5^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_V5))
		case "131336^MDC_ECG_ELEC_POTL_V6^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_V6))
		case "131389^MDC_ECG_ELEC_POTL_III^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_III))
		case "131390^MDC_ECG_ELEC_POTL_AVR^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_AVR))
		case "131391^MDC_ECG_ELEC_POTL_AVL^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_AVL))
		case "131392^MDC_ECG_ELEC_POTL_AVF^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_AVF))
		case "131395^MDC_ECG_ELEC_POTL_V^MDC":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_ECG_ELEC_POTL_V))
		case "150452^MDC_PULS_OXIM_PLETH":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_PULS_OXIM_PLETH))
		case "151828^MDC_QUO_RESP":
			pkt.Data = append(pkt.Data, m.PackOBX(obx, ecgpacket.EcgChan_CHAN_QUO_RESP))
		}
	}

	return &pkt
}

func (m *hl7_WaveBlock) parse(segs []hl7d.Segment) bool {
	if len(segs) < 2 {
		return false
	}

	if !m.obr.parse(segs[0]) {
		return false
	}

	m.obx = make([]hl7_OBX_WaveformBlock, 0)
	for _, seg := range segs[1:] {
		obx := hl7_OBX_WaveformBlock{}
		if obx.parse(seg) {
			m.obx = append(m.obx, obx)
		}
	}

	return true
}

type hl7_Alarm struct {
	obr hl7_OBR_Alert
	obx []hl7_OBX_Alert
}

// func (m *hl7_Alarm) Packet(ctx context.Context) []*ecgpacket.Packet {
// 	fmt.Println("hl7_Alarm Packet")
// 	ctxval, ok := ctx.Value(RawDataInfoKey).(RawDataInfoValue)
// 	if !ok {
// 		logger.Info("Pack Wave OBX error: no context")
// 		return nil
// 	}

// 	alarmdatreturn  &ecgpacket.EcgAlarmDataPacket{}
// 	for _, obx := range m.obx {
// 		fmt.Println("OBX:", obx.OBX3_OversationIdentifier)
// 		switch obx.OBX3_OversationIdentifier {
// 		case "196616^MDC_EVT_ALARM^MDC": // Facet 1: alert event type
// 		case "68480^MDC_ATTR_ALERT_SOURCE^MDC":
// 		case "68481^MDC_ATTR_EVENT_PHASE^MDC":
// 		case "68482^MDC_ATTR_ALARM_STATE^MDC":
// 		case "68483^MDC_ATTR_ALARM_INACTIVATION_STATE^MDC":
// 		case "68484^MDC_ATTR_ALARM_PRIORITY^MDC":
// 		case "68485^MDC_ATTR_ALERT_TYPE^MDC":
// 		case "68486^MDC_ATTR_ALERT_THRESHOLD^MDC":
// 		}
// 	}

// 	ecgreturn  &ecgpacket.Packet{
// 		Alarmpkt: &ecgpacket.EcgAlarmPacket{
// 			Ts:  ctxval.Ts,
// 			Seq: ctxval.Seq,
// 			Uid: ctxval.Uid,
// 			Als: []*ecgpacket.EcgAlarmDataPacket{alarmdatpkt},
// 		},
// 	}
// 	return []*ecgpacket.Packet{ecgpkt}
// }

func (m *hl7_Alarm) parse(segs []hl7d.Segment) bool {
	if len(segs) < 2 {
		return false
	}

	if !m.obr.parse(segs[0]) {
		return false
	}

	m.obx = make([]hl7_OBX_Alert, 0)
	for _, seg := range segs[1:] {
		obx := hl7_OBX_Alert{}
		if obx.parse(seg) {
			m.obx = append(m.obx, obx)
		}
	}

	return true
}

type hl7_msg struct {
	msh   hl7_MSH
	pid   hl7_PID
	pv1   hl7_PV1
	obs   *hl7_ObservationBlock
	wave  *hl7_WaveBlock
	alarm *hl7_Alarm
}

func (m *hl7_msg) Convert() *ecgpacket.Packet {
	if m.obs != nil {
		return m.obs.Convert()
	}

	if m.wave != nil {
		return m.wave.Convert()
	}

	if m.alarm != nil {
		// return m.alarm.Packet(ctx)
	}

	return nil
}

type HL7Decoder struct{}

func NewHL7Decoder() *HL7Decoder {
	return &HL7Decoder{}
}

func (d *HL7Decoder) Decode(dat []byte) []*ecgpacket.Packet {
	msgs, err := hl7d.NewDecoder(bytes.NewBuffer(dat)).Messages()
	if err != nil {
		return nil
	}

	// 把HL7消息转到hl7_msg数据里
	hl7msgs := make([]hl7_msg, 0)
	for i := 0; i < len(msgs); i++ {
		msg := hl7_msg{}
		if len(msgs[i].Segments) < 5 { // msh, pid, pv1, obr, obx...
			return nil
		}

		obs := hl7_ObservationBlock{}
		wave := hl7_WaveBlock{}
		alarm := hl7_Alarm{}

		// parse MSH/PID/PV1
		if !msg.msh.parse(msgs[i].Segments[0]) ||
			!msg.pid.parse(msgs[i].Segments[1]) ||
			!msg.pv1.parse(msgs[i].Segments[2]) {
			goto _msg_error
		}

		// try parse observation block
		if obs.parse(msgs[i].Segments[3:]) {
			msg.obs = &obs
			goto _msg_ok
		}

		// try parse Wave block
		if wave.parse(msgs[i].Segments[3:]) {
			msg.wave = &wave
			goto _msg_ok
		}

		// try parse Alarm
		if alarm.parse(msgs[i].Segments[3:]) {
			msg.alarm = &alarm
			goto _msg_ok
		}

	_msg_ok:
		hl7msgs = append(hl7msgs, msg)
		continue

	_msg_error:
		logger.Info("parse hl7_msg failed")
		continue
	}

	if len(hl7msgs) == 0 {
		return nil
	}

	// 把hl7_msg转EcgPacket
	ret := make([]*ecgpacket.Packet, 0)
	for _, msg := range hl7msgs {
		pkt := msg.Convert()
		if pkt != nil {
			ret = append(ret, pkt)
		}
	}

	return ret
}
